package com.shortlink.auth.util;

import cn.hutool.core.util.ObjectUtil;
import com.shortlink.common.exception.ServiceException;
import com.shortlink.common.user.UserInfoDTO;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 *
 * @author wp
 */
@Component
@Setter
@Getter
@ConfigurationProperties(value = "shortlink-auth.token")
public class JwtUtils {
    private static final String USER_ID = "userId";
    private static final String USERNAME = "username";
    private static final String GROUP_NAME = "groupName";
    private static final String GROUP_LEVEL = "groupLevel";

    /**
     * 密钥
     */
    private String secret;
    /**
     * 有效期
     */
    private long jwtExpiration;

    /**
     * 生成JWT令牌
     */
    public String generateToken(UserInfoDTO userInfoDTO) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + jwtExpiration);

        Map<String, Object> map = new HashMap<>();
        map.put(USER_ID, userInfoDTO.getUserId());
        map.put(USERNAME, userInfoDTO.getUsername());
        map.put(GROUP_NAME, userInfoDTO.getGroupName());
        map.put(GROUP_LEVEL, userInfoDTO.getGroupLevel());
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        return Jwts.builder()
                .subject(userInfoDTO.getUserId().toString())
                .claims(map)
                .issuedAt(now)
                .expiration(expiryDate)
                .signWith(key)
                .compact();
    }

    /**
     * 解析JWT令牌
     */
    public UserInfoDTO parseToken(String token) {
        if (ObjectUtil.isEmpty(token)) {
            return null;
        }
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        Claims claims;
        try {
            claims = Jwts.parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (JwtException e) {
            return null;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new ServiceException("JWT解析错误");
        }
        return UserInfoDTO.builder()
                .userId(claims.get(USER_ID, Long.class))
                .username(claims.get(USERNAME, String.class))
                .groupName(claims.get(GROUP_NAME, String.class))
                .groupLevel(claims.get(GROUP_LEVEL, Integer.class))
                .build();
    }
}